int CLK_PIN = 2;
int IN_PIN = 4;
int OUT_PIN = 6;
int LED_PIN = 13;

int DELAY = 60;







byte mask = 1;

void setup(){


  Serial.begin(9600); 


  Serial.println("SuperMario"); 


  /* Setup pins */
  pinMode(CLK_PIN, OUTPUT);                                               
  pinMode(OUT_PIN, OUTPUT);                                              
  pinMode(IN_PIN, INPUT); 
  
  digitalWrite(IN_PIN, HIGH);   // Internal pull-up for the Input port 


 
  digitalWrite(CLK_PIN, HIGH);  // Reset clock to idle
}


void cmdFin(){
  unsigned int crc = 0;
  
 /* Line package */
  writeByte(0x88); // Sync #1
  writeByte(0x33); // Sync #2

  writeByte(0x04); // Command Type Enquiry
  crc+= 0x04;
  
  writeByte(0x00); // Compression. Off

  writeByte(0x00); 
  writeByte(0x00);




  writeInt(crc);

  writeByte(0x00);  
  writeByte(0x00); // Provoke ACK

  

 
}


void cmdLine(){
  unsigned int crc = 0;
  
 /* Line package */
  writeByte(0x88); // Sync #1
  writeByte(0x33); // Sync #2

  writeByte(0x04); // Command Type Enquiry
  crc+= 0x04;
  
  writeByte(0x00); // Compression. Off

  writeByte(0x80); crc+=0x80;
  writeByte(0x02); crc+=0x02;

  for(int i = 0; i< 40*16; i++){

      byte val = i/3;
      
    
      writeByte(val);
      

      crc += val;
  
  }


  writeInt(crc);

  writeByte(0x00);  
  writeByte(0x00); // Provoke ACK

  

 
}

void cmdEnq(){
  
  /* Sample package */
  writeByte(0x88); // Sync #1
  writeByte(0x33); // Sync #2

  writeByte(0x0F); // Command Type Enquiry
  writeByte(0x00); // Compression. Off

  writeByte(0x00);
  writeByte(0x00);

  writeInt(0x0F);

  writeByte(0x00);  
  writeByte(0x00); // Provoke ACK
}

void cmdInit(){
    /* Init package */
  writeByte(0x88); // Sync #1
  writeByte(0x33); // Sync #2

  writeByte(0x01); // Command Type Enquiry
  writeByte(0x00); // Compression. Off

  writeByte(0x00);
  writeByte(0x00);

  writeByte(0x01);
  writeByte(0x00);

  writeByte(0x00);  
  writeByte(0x00); // Provoke ACK
}

void cmdPrnt(){
    /* Start printing package */
  writeByte(0x88); // Sync #1
  writeByte(0x33); // Sync #2

  writeByte(0x02); // Command Type Start Printing
  writeByte(0x00); // Compression. Off

  writeByte(0x04);
  writeByte(0x00);

  writeByte(0x01);
  writeByte(0x13);

    writeByte(0xe4);
        writeByte(0x40);


    writeByte(0x3e);
        writeByte(0x01);


  writeByte(0x00);  
  writeByte(0x00); // Provoke ACK 
}


void cmdPrntWo(){
    /* Start printing package */
  writeByte(0x88); // Sync #1
  writeByte(0x33); // Sync #2

  writeByte(0x02); // Command Type Start Printing
  writeByte(0x00); // Compression. Off

  writeByte(0x04);
  writeByte(0x00);

  writeByte(0x01);
  writeByte(0x00); // No margin

    writeByte(0xe4);
        writeByte(0x40);


    writeInt(299);


  writeByte(0x00);  
  writeByte(0x00); // Provoke ACK 
}

void loop(){


 
  
  cmdEnq();

 // delay(10000);
  
  cmdInit();
  
  cmdLine();



      
       cmdLine();   
  
    cmdFin();
   //   cmdLine();
    //    cmdLine();
  
 cmdPrntWo();
  
  delay(1000);



  /* Try to read ack */
  byte value1 = 0;

  for(int n = 7; n>=0; n--){
    // delayMicroseconds(DELAY);
  //  digitalWrite(CLK_PIN, LOW);
   // delayMicroseconds(DELAY);

    if( digitalRead(IN_PIN) == HIGH ){
      value1 |= (1 << n);       // forces nth bit of x to be 1.  all other bits left alone.

    }
    else {
      value1 &= ~(1 << n);      // forces nth bit of x to be 0.  all other bits left alone.

    }

  //  digitalWrite(CLK_PIN, HIGH);
        delayMicroseconds(DELAY);

  }



  /* Try to read ack */
  byte value2 = 0;

  for(int n = 7; n>=0; n--){
    //delayMicroseconds(DELAY);
   // digitalWrite(CLK_PIN, LOW);
    // delayMicroseconds(DELAY);

    if( digitalRead(IN_PIN) == HIGH ){
      value2 |= (1 << n);       // forces nth bit of x to be 1.  all other bits left alone.

    }
    else {
      value2 &= ~(1 << n);      // forces nth bit of x to be 0.  all other bits left alone.
    }
    
  //  digitalWrite(CLK_PIN, HIGH);
        delayMicroseconds(DELAY);



  }

  Serial.println(value1, HEX);
  Serial.println(value2, HEX);
  Serial.println("---");

//  digitalWrite(CLK_PIN, HIGH);






  delay(1000);

}

void writeInt(unsigned int i){
  
  writeByte((byte)(i));   // LsB
  
  writeByte((byte)(i>>8));   // MsB
}

void oldWriteByte(byte b){

  for (mask = 00000001; mask>0; mask <<= 1) { //iterate through bit mask
    if (b & mask){ // if bitwise AND resolves to true
      digitalWrite(OUT_PIN,LOW); // send 1
    }
    else{ //if bitwise and resolves to false
      digitalWrite(OUT_PIN,HIGH); // send 0
    }


    digitalWrite(CLK_PIN, LOW);
    // delayMicroseconds(DELAY);
    //Serial.print(digitalRead(IN_PIN));
    digitalWrite(CLK_PIN, HIGH);
    // delayMicroseconds(DELAY);


  }

}

void writeByte(byte b)
{
  for(int i=0;i<8;i++) {  //NEWS FLASH: there are 8 bits in a byte
    digitalWrite(CLK_PIN,LOW);                            //Set the clock to zero, wes about to send you somethin
    if(b & 0x80) {                                   //Magic
      digitalWrite(OUT_PIN,HIGH);                     //1
    } else {
      digitalWrite(OUT_PIN,LOW);                      //0
    }
    b <<= 1;            //More magic
    delayMicroseconds(DELAY);
    digitalWrite(CLK_PIN,HIGH);                           //Make the clock 1, so we can make a funky squarewave
          delayMicroseconds(DELAY);
  }
  digitalWrite(OUT_PIN,LOW);                          //We are done, turn the serial off

}





